#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include "psclient.h"
#include "atomic.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <errno.h>

long client = 0;
long max = 0;

CPSClient::CPSClient(int sock, IPSMonitor* mon)
: m_sock(sock)
, m_monitor(mon)
{
	m_count = 0;
	client++;
	if(client > max) max = client;
	m_nRef = 1;
	printf("%d [%d,%d]new: %d\n", sock, client, max, this);
}

CPSClient::~CPSClient()
{
	int				sock;
	
	if(-1 != m_sock)
	{
		if(0 != m_monitor)
		{
			m_monitor->DelMonitor(this);
		}

		sock = m_sock;
		m_sock = -1;
		close(sock);
	}
	client--;
	printf("[%d,%d]delete: %d\n", client, max, this);
}

int CPSClient::GetEventFd()
{
	return m_sock;
}

void CPSClient::OnEventIn()
{
	char	szRead[4097]	= {0};
	int		n;

	n = recv(m_sock, szRead, 4096, 0);
	if(0 == n)
	{
		m_monitor->DelMonitor(this);
		OnEventError();
		return;
	}

	OnRecv(szRead, n);
}
	
void CPSClient::OnEventOut()
{
}

void CPSClient::OnEventPri()
{
}

void CPSClient::OnEventError()
{
	int		sock = m_sock;
	
	m_sock = -1;
	close(sock);
	Release();
}

long CPSClient::AddRef()
{
	return InterlockedIncrement(&m_nRef);
}

long CPSClient::Release()
{
	long	ref		= InterlockedDecrement(&m_nRef);

	if(ref <= 0)
	{
		delete this;
	}

	return ref;
}

void CPSClient::OnRecv(char* pData, int nLen)
{
	time_t		t;
	struct tm	tm;
	char		szTime[128]		= {0};
	char		szData[4096]	= {0};

	if(0 != m_count)
	{
		printf("%s\n", pData);
		return;
	}

	m_count++;
	t = time(NULL);
	localtime_r(&t, &tm);
	sprintf(szTime, "%04d-%02d-%02d %02d:%02d:%02d"
			, tm.tm_year + 1900
			, tm.tm_mon + 1
			, tm.tm_mday
			, tm.tm_hour
			, tm.tm_min
			, tm.tm_sec);

//	strcpy(szTime, "xxxx-xx-xx xx:xx:xx");
	sprintf(szData, "HTTP/1.1 200 OK\r\n"
			"Server: Linux\r\n"
			"Content-Type: text/html;charset=utf-8\r\n"
			"Content-Length: %d\r\n"
			"Connection: Close\r\n"
			"\r\n%s"
			, strlen(szTime)
			, szTime);
	send(m_sock, szData, strlen(szData), 0);
}

bool CPSClient::Init(void)
{
	// 异步
	unsigned long	ul	= 1;

	// ioctl(sock, FIONBIO, &ul);
	// 修改属性
	int		keepalive		= 1;	// 开启keepalive
	int		keepidle		= 60;	// 如果60秒内没有任何数据则重试
	int		keepinterval	= 1;	// 重试时间间隔
	int		keepcount		= 5;	// 重试5次

	setsockopt(m_sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalive, sizeof(keepalive));
	setsockopt(m_sock, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle, sizeof(keepidle));
	setsockopt(m_sock, SOL_TCP, TCP_KEEPINTVL, (void*)&keepinterval, sizeof(keepinterval));
	setsockopt(m_sock, SOL_TCP, TCP_KEEPCNT, (void*)&keepcount, sizeof(keepcount));
	// 添加监视
	if(NULL == m_monitor)
	{
		return false;
	}

	if(false == m_monitor->AddMonitor(this, EPOLLIN /*| EPOLLET | EPOLLONESHOT*/))
	{
		return false;
	}
	
	return true;	
}

IPSClient* CPSClient::Create(int sock, IPSMonitor* mon)
{
	CPSClient*		p	= new CPSClient(sock, mon);

	if( !p->Init() )
	{
		p->Release();
		return NULL;
	}

	return p;
}
